package com.sinping.qh.repository.mongo.lab.impl;

import com.google.common.collect.Lists;
import com.sinping.qh.dto.admin.ApiBuildingDto;
import com.sinping.qh.dto.admin.ApiUnitDto;
import com.sinping.qh.query.base.AggregateParams;
import com.sinping.qh.repository.mongo.lab.LaboratoryRepository;
import com.sinping.qh.service.MongoManager;
import com.sinping.qh.service.admin.impl.LaboratoryServiceImpl;
import com.sinping.qh.service.common.CommonDbConst;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

/**
 * @author jiahuaiqing
 * @create 2018/7/9
 */
@Service
public class LabRepositoryImpl {

    @Autowired
    LaboratoryRepository laboratoryRepository;

    @Autowired
    private MongoTemplate template;

    @Autowired
    private MongoManager mongoManager;
    @Autowired
    private LaboratoryServiceImpl laboratoryServiceImpl;


    /**
     * 参考了CheckRecordServiceImpl$findPageByUniting 的分组查询
     * @param userID
     * @param groupParams
     * @param aggregateParams
     * @param clazz
     * @param targetClazz
     * @param <T>
     * @return
     */
    public <T> List<T> findPageByUserId(String userID,List<String> groupParams,
                                        PageRequest page,AggregateParams aggregateParams,
                                         Class<?> clazz, Class<T> targetClazz) {
        List<AggregationOperation> operations = Lists.newArrayList();


        //添加权限
//        Criteria mainCriteria =new Criteria();
//        Criteria one =Criteria.where("check_unit_id").in(unitIDList);
//        Criteria two =Criteria.where("check_lab_id").in(labIDList);
//        mainCriteria.orOperator(one,two);
//        operations.add(Aggregation.match(mainCriteria));

        /**当前登录用户*/
        Criteria userid = Criteria.where("user_id").is(userID);
        operations.add(Aggregation.match(userid));

        /**院系/实验室有效*/
        Criteria status = Criteria.where("status").is(CommonDbConst.DB_DELETE_NORMAL);
        operations.add(Aggregation.match(status));


        Criteria type = Criteria.where("type").is(CommonDbConst.USER_MANAGER_LAB);
        operations.add(Aggregation.match(type));


        List<ApiUnitDto> userManagerLabInUnit = laboratoryServiceImpl.getUserManagerLabInUnit(userID);
        List<String>unitIdList=new ArrayList<>();
        for (ApiUnitDto apiUnitDto: userManagerLabInUnit) {
            unitIdList.add(apiUnitDto.getId());
        }
        /**属于当前登录用户负责实验室所在的院系*/
        Criteria unitIdListCriteria = Criteria.where("manager_unit_id").in(unitIdList);
        operations.add(Aggregation.match(unitIdListCriteria));


        List<ApiBuildingDto> userManagerLabInBuilding = laboratoryServiceImpl.getUserManagerLabInBuilding(userID);

        List<String>buildingIdList=new ArrayList<>();
        for (ApiBuildingDto apiBuildingDto: userManagerLabInBuilding) {
            buildingIdList.add(apiBuildingDto.getId());
        }
        /**属于当前登录用户负责实验室所在的楼宇*/
        Criteria buildingIdListCriteria = Criteria.where("lab_building_id").in(buildingIdList);
        operations.add(Aggregation.match(buildingIdListCriteria));

        if (page!=null){
            SortOperation sortOperation = new SortOperation(page.getSort());
            operations.add(sortOperation);
            SkipOperation skipOperation = new SkipOperation(page.getOffset());
            operations.add(skipOperation);
            LimitOperation limitOperation = new LimitOperation(page.getPageSize());
            operations.add(limitOperation);

        }

        // 统计参数
        GroupOperation group = Aggregation.group(groupParams.toArray(new String[groupParams.size()]));
        for (String name : aggregateParams.getFieldNames()) {
            switch (aggregateParams.getAggregateOperator(name)) {
                case avg:
                    group = group.avg(name).as(aggregateParams.getAlias(name));
                    break;
                case max:
                    group = group.max(name).as(aggregateParams.getAlias(name));
                    break;
                case min:
                    group = group.min(name).as(aggregateParams.getAlias(name));
                    break;
                case sum:
                    group = group.sum(name).as(aggregateParams.getAlias(name));
                    break;
                case last:
                    group = group.last(name).as(aggregateParams.getAlias(name));
                    break;
                case first:
                    group = group.first(name).as(aggregateParams.getAlias(name));
                    break;
                case count:
                default:
                    group = group.count().as(aggregateParams.getAlias(name));
                    break;
            }
        }
        operations.add(group);


        Aggregation aggregation = Aggregation.newAggregation(operations);
        String table = template.getCollectionName(clazz);
        AggregationResults<T> results = template.aggregate(aggregation, table, targetClazz);
        return results.getMappedResults();
    }

    /**
     * 根据用户id,获取所负责的实验室列表
     * @param managerUnitId
     * @param clazz
     * @param targetClazz
     * @param <T>
     * @return
     */
    public <T> List<T> findPageByUnitId(String managerUnitId,String userId, PageRequest page, Class<?> clazz, Class<T> targetClazz) {
        List<AggregationOperation> operations = Lists.newArrayList();

        //添加权限
//        Criteria mainCriteria =new Criteria();
//        Criteria one =Criteria.where("check_unit_id").in(unitIDList);
//        Criteria two =Criteria.where("check_lab_id").in(labIDList);
//        mainCriteria.orOperator(one,two);
//        operations.add(Aggregation.match(mainCriteria));

        Criteria managerCriteria = Criteria.where("manager_unit_id").is(managerUnitId)
                .and("user_id").is(userId);
        operations.add(Aggregation.match(managerCriteria));


        //查询隐患记录数据不为0和隐患状态未完成的检查记录
        LookupOperation lookupOperation
                =LookupOperation.newLookup()
                .from("tb_lab")
                .localField("manager_lab_id")
                .foreignField("_id")
                .as("labrecords");
        operations.add(lookupOperation);

        Criteria criteria=Criteria.where("labrecords").ne(new HashSet<>()).and("status").is("0").and("labrecords.status").is("0");
        operations.add(Aggregation.match(criteria));

        if (page!=null){
            SkipOperation skipOperation = new SkipOperation(page.getOffset());
            operations.add(skipOperation);
            LimitOperation limitOperation = new LimitOperation(page.getPageSize());
            operations.add(limitOperation);
            SortOperation sortOperation = new SortOperation(page.getSort());
            operations.add(sortOperation);
        }

        Aggregation aggregation = Aggregation.newAggregation(operations);
        String table = template.getCollectionName(clazz);
        AggregationResults<T> results = template.aggregate(aggregation, table, targetClazz);
        return results.getMappedResults();
    }





    public <T> List<T> findPageByUnitingDetail(List<String> unitIDList,
                                               List<String> labIDList,
                                               String checkUnidId,String checkBuildingId,Class<T> clazz)
    {
        List<AggregationOperation> operations = Lists.newArrayList();
        //添加权限
        Criteria mainCriteria =new Criteria();
//        Criteria one =Criteria.where("check_unit_id").in(unitIDList);
//        Criteria two =Criteria.where("check_lab_id").in(labIDList);
//        mainCriteria.orOperator(one,two);

        //查询传入的检查院系和楼宇
        mainCriteria.and("check_unit_id").is(checkUnidId).and("check_building_id").is(checkBuildingId);

        operations.add(Aggregation.match(mainCriteria));

        //查询隐患记录数据不为0和隐患状态未完成的检查记录
        LookupOperation lookupOperation
                =LookupOperation.newLookup()
                .from("tb_hidden_danger")
                .localField("_id")
                .foreignField("check_id")
                .as("hidenrecords");
        operations.add(lookupOperation);

        HashSet<String> hiddStatus=new HashSet<>();
        hiddStatus.add("0");
        hiddStatus.add("1");
        hiddStatus.add("2");
        Criteria criteria=Criteria.where("hidenrecords").ne(new HashSet<>())
                .and("hidenrecords.hidden_danger_status").in(hiddStatus);
        operations.add(Aggregation.match(criteria));

        Aggregation aggregation = Aggregation.newAggregation(operations);
        String table = template.getCollectionName(clazz);
        AggregationResults<T> results = template.aggregate(aggregation, table, clazz);

        return results.getMappedResults();
    }
}
